﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using Centido.Core.Dto;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Centido.Core.Test
{
    /// <summary>
    ///   Testing the data transfer object for a backup.
    /// </summary>
    [TestClass]
    public class BackupDtoTest : GenericDtoTest
    {
        /// <summary>
        ///   Retrieves the name of the data transfer object xml tag.
        /// </summary>
        /// <returns></returns>
        protected override string GetXmlTag()
        {
            return BackupDto.XmlTag;
        }


        /// <summary>
        ///   Retrives the current xml schema version.
        /// </summary>
        /// <returns></returns>
        protected override string GetCurrentXmlSchemaVersion()
        {
            return BackupDto.CurrentXmlSchemaVersion;
        }


        /// <summary>
        ///   Creates a new data transfer object.
        /// </summary>
        /// <returns></returns>
        protected override DataTransferObject CreateDto()
        {
            return new BackupDto
            {
                CreatedBy = StringProperty.RandomIdentifier(),
                CreatedOn = DateTime.Now
            };
        }


        /// <summary>
        ///   Retrieves the list of data transfer object fields.
        /// </summary>
        /// <returns></returns>
        protected override IEnumerable<DtoFieldInfo> GetFields()
        {
            yield return new DtoFieldInfo
            {
                Name = "CreatedBy",
                XmlName = BackupDto.CreatedByAttribute,
                IsRequired = false,
                FieldType = DtoFieldType.String,
                SampleValue = StringProperty.RandomIdentifier(),
                IsCopiedFromDto = false
            };

            yield return new DtoFieldInfo
            {
                Name = "CreatedOn",
                XmlName = BackupDto.CreatedOnAttribute,
                IsRequired = false,
                FieldType = DtoFieldType.String,
                SampleValue = DateTime.Now.AddDays(-5)
            };
        }


        /// <summary>
        ///   Copies the properties of the data transfer object to the corresponding object.
        /// </summary>
        /// <param name="dto">The data transfer object.</param>
        /// <returns>Returns the corresponding object after copying.</returns>
        protected override object CopyFrom(DataTransferObject dto)
        {
            return null;
        }


        /// <summary>
        ///   Creates a data transfer object from the correpsonding object.
        /// </summary>
        /// <param name="dto">The created data transfer object.</param>
        /// <param name="initialObject">The initial object.</param>
        protected override void CreateDtoFromObject(out DataTransferObject dto, out object initialObject)
        {
            dto = null;
            initialObject = null;
        }


        /// <summary>
        ///   Reading the table list from xml.
        /// </summary>
        [TestMethod]
        public void ReadingTableListFromXml()
        {
            // Creating a backup
            var xml = string.Format("<{0}>",
                BackupDto.XmlTag);

            // Creating the table list
            xml += string.Format("<{0}><{1} {2}=\"{3}\" /><{4} {5}=\"{6}\"></{7}></{8}></{9}>",
                BackupDto.TableListTag,
                TableDto.XmlTag,
                TableDto.NameAttribute,
                StringProperty.RandomIdentifier(),
                TableDto.XmlTag,
                TableDto.NameAttribute,
                StringProperty.RandomIdentifier(),
                TableDto.XmlTag,
                BackupDto.TableListTag,
                BackupDto.XmlTag);

            var stream = new XmlTextReader(new MemoryStream(Encoding.UTF8.GetBytes(xml)));

            var dto = new BackupDto();

            dto.ReadXml(stream);

            Assert.AreEqual(dto.Tables.Count(), 2);
        }


        /// <summary>
        ///   Reading an empty table list.
        /// </summary>
        [TestMethod]
        public void ReadingEmptyTableListFromXml()
        {
            // Creating a backup
            var xml = string.Format("<{0}>",
                BackupDto.XmlTag);

            // Creating an empty table list
            xml += string.Format("<{0}></{1}></{2}>",
                BackupDto.TableListTag,
                BackupDto.TableListTag,
                BackupDto.XmlTag);

            var stream = new XmlTextReader(new MemoryStream(Encoding.UTF8.GetBytes(xml)));

            var dto = new BackupDto();

            dto.ReadXml(stream);

            Assert.AreEqual(dto.Tables.Count(), 0);
        }


        /// <summary>
        ///   Writing and reading the table list.
        /// </summary>
        [TestMethod]
        public void WritingAndReadingTableList()
        {
            var backupDto = new BackupDto();

            backupDto.AddTable(new TableDto
            {
                Name = "table_1"
            });

            backupDto.AddTable(new TableDto
            {
                Name = "table_2"
            });

            var memoryStream = new MemoryStream();
            var writer = new XmlTextWriter(memoryStream, Encoding.UTF8);

            backupDto.WriteXml(writer);

            writer.Flush();

            memoryStream.Position = 0;
            var streamReader = new StreamReader(memoryStream);
            var xml = streamReader.ReadToEnd();

            Assert.IsFalse(string.IsNullOrEmpty(xml));

            memoryStream.Position = 0;
            var reader = new XmlTextReader(memoryStream);

            var dto = new BackupDto();

            dto.ReadXml(reader);

            Assert.AreEqual(dto.Tables.Count(), 2);
        }


        /// <summary>
        ///   Reading the unit list from xml.
        /// </summary>
        [TestMethod]
        public void ReadingUnitListFromXml()
        {
            // Creating a backup
            var xml = string.Format("<{0}>",
                BackupDto.XmlTag);

            // Creating the unit list
            xml += string.Format("<{0}><{1} {2}=\"{3}\" /><{4} {5}=\"{6}\"></{7}></{8}></{9}>",
                BackupDto.UnitListTag,
                UnitDto.XmlTag,
                UnitDto.NameAttribute,
                StringProperty.RandomIdentifier(),
                UnitDto.XmlTag,
                UnitDto.NameAttribute,
                StringProperty.RandomIdentifier(),
                UnitDto.XmlTag,
                BackupDto.UnitListTag,
                BackupDto.XmlTag);

            var stream = new XmlTextReader(new MemoryStream(Encoding.UTF8.GetBytes(xml)));

            var dto = new BackupDto();

            dto.ReadXml(stream);

            Assert.AreEqual(dto.Units.Count(), 2);
        }


        /// <summary>
        ///   Reading an empty unit list from xml.
        /// </summary>
        [TestMethod]
        public void ReadingEmptyUnitListFromXml()
        {
            // Creating a backup
            var xml = string.Format("<{0}>",
                BackupDto.XmlTag);

            // Creating an empty unit list
            xml += string.Format("<{0}></{1}></{2}>",
                BackupDto.UnitListTag,
                BackupDto.UnitListTag,
                BackupDto.XmlTag);

            var stream = new XmlTextReader(new MemoryStream(Encoding.UTF8.GetBytes(xml)));

            var dto = new BackupDto();

            dto.ReadXml(stream);

            Assert.AreEqual(dto.Units.Count(), 0);
        }


        /// <summary>
        ///   Writing and reading the unit list.
        /// </summary>
        [TestMethod]
        public void WritingAndReadingUnitList()
        {
            var backupDto = new BackupDto();

            backupDto.AddUnit(new UnitDto
            {
                Name = StringProperty.RandomIdentifier()
            });

            backupDto.AddUnit(new UnitDto
            {
                Name = StringProperty.RandomIdentifier()
            });

            var memoryStream = new MemoryStream();
            var writer = new XmlTextWriter(memoryStream, Encoding.UTF8);

            backupDto.WriteXml(writer);

            writer.Flush();

            memoryStream.Position = 0;
            var streamReader = new StreamReader(memoryStream);
            var xml = streamReader.ReadToEnd();

            Assert.IsFalse(string.IsNullOrEmpty(xml));

            memoryStream.Position = 0;
            var reader = new XmlTextReader(memoryStream);

            var dto = new BackupDto();

            dto.ReadXml(reader);

            Assert.AreEqual(dto.Units.Count(), 2);
        }


        /// <summary>
        ///   Reading the role list from xml.
        /// </summary>
        [TestMethod]
        public void ReadingRoleListFromXml()
        {
            // Creating a backup
            var xml = string.Format("<{0}>",
                BackupDto.XmlTag);

            // Creating the role list
            xml += string.Format("<{0}><{1} {2}=\"{3}\" /><{4} {5}=\"{6}\"></{7}></{8}></{9}>",
                BackupDto.RoleListTag,
                RoleDto.XmlTag,
                RoleDto.NameAttribute,
                StringProperty.RandomIdentifier(),
                RoleDto.XmlTag,
                RoleDto.NameAttribute,
                StringProperty.RandomIdentifier(),
                RoleDto.XmlTag,
                BackupDto.RoleListTag,
                BackupDto.XmlTag);

            var stream = new XmlTextReader(new MemoryStream(Encoding.UTF8.GetBytes(xml)));

            var dto = new BackupDto();

            dto.ReadXml(stream);

            Assert.AreEqual(dto.Roles.Count(), 2);
        }


        /// <summary>
        ///   Reading an empty role list from xml.
        /// </summary>
        [TestMethod]
        public void ReadingEmptyRoleListFromXml()
        {
            // Creating a backup
            var xml = string.Format("<{0}>",
                BackupDto.XmlTag);

            // Creating an empty role list
            xml += string.Format("<{0}></{1}></{2}>",
                BackupDto.RoleListTag,
                BackupDto.RoleListTag,
                BackupDto.XmlTag);

            var stream = new XmlTextReader(new MemoryStream(Encoding.UTF8.GetBytes(xml)));

            var dto = new BackupDto();

            dto.ReadXml(stream);

            Assert.AreEqual(dto.Roles.Count(), 0);
        }


        /// <summary>
        ///   Writing and reading the role list.
        /// </summary>
        [TestMethod]
        public void WritingAndReadingRoleList()
        {
            var backupDto = new BackupDto();

            backupDto.AddRole(new RoleDto
            {
                Name = StringProperty.RandomIdentifier()
            });

            backupDto.AddRole(new RoleDto
            {
                Name = StringProperty.RandomIdentifier()
            });

            var memoryStream = new MemoryStream();
            var writer = new XmlTextWriter(memoryStream, Encoding.UTF8);

            backupDto.WriteXml(writer);

            writer.Flush();

            memoryStream.Position = 0;
            var streamReader = new StreamReader(memoryStream);
            var xml = streamReader.ReadToEnd();

            Assert.IsFalse(string.IsNullOrEmpty(xml));

            memoryStream.Position = 0;
            var reader = new XmlTextReader(memoryStream);

            var dto = new BackupDto();

            dto.ReadXml(reader);

            Assert.AreEqual(dto.Roles.Count(), 2);
        }


        /// <summary>
        ///   Reading the role list from xml.
        /// </summary>
        [TestMethod]
        public void ReadingUserListFromXml()
        {
            // Creating a backup
            var xml = string.Format("<{0}>",
                BackupDto.XmlTag);

            // Creating the user list
            xml += string.Format("<{0}><{1} {2}=\"{3}\" /><{4} {5}=\"{6}\"></{7}></{8}></{9}>",
                BackupDto.UserListTag,
                UserDto.XmlTag,
                UserDto.NameAttribute,
                StringProperty.RandomIdentifier(),
                UserDto.XmlTag,
                UserDto.NameAttribute,
                StringProperty.RandomIdentifier(),
                UserDto.XmlTag,
                BackupDto.UserListTag,
                BackupDto.XmlTag);

            var stream = new XmlTextReader(new MemoryStream(Encoding.UTF8.GetBytes(xml)));

            var dto = new BackupDto();

            dto.ReadXml(stream);

            Assert.AreEqual(dto.Users.Count(), 2);
        }


        /// <summary>
        ///   Reading an empty user list from xml.
        /// </summary>
        [TestMethod]
        public void ReadingEmptyUserListFromXml()
        {
            // Creating a backup
            var xml = string.Format("<{0}>",
                BackupDto.XmlTag);

            // Creating the user list
            xml += string.Format("<{0}></{1}></{2}>",
                BackupDto.UserListTag,
                BackupDto.UserListTag,
                BackupDto.XmlTag);

            var stream = new XmlTextReader(new MemoryStream(Encoding.UTF8.GetBytes(xml)));

            var dto = new BackupDto();

            dto.ReadXml(stream);

            Assert.AreEqual(dto.Users.Count(), 0);
        }


        /// <summary>
        ///   Writing and reading the user list.
        /// </summary>
        [TestMethod]
        public void WritingAndReadingUserList()
        {
            var backupDto = new BackupDto();

            backupDto.AddUser(new UserDto
            {
                Name = StringProperty.RandomIdentifier()
            });

            backupDto.AddUser(new UserDto
            {
                Name = StringProperty.RandomIdentifier()
            });

            var memoryStream = new MemoryStream();
            var writer = new XmlTextWriter(memoryStream, Encoding.UTF8);

            backupDto.WriteXml(writer);

            writer.Flush();

            memoryStream.Position = 0;
            var streamReader = new StreamReader(memoryStream);
            var xml = streamReader.ReadToEnd();

            Assert.IsFalse(string.IsNullOrEmpty(xml));

            memoryStream.Position = 0;
            var reader = new XmlTextReader(memoryStream);

            var dto = new BackupDto();

            dto.ReadXml(reader);

            Assert.AreEqual(dto.Users.Count(), 2);
        }


        /// <summary>
        ///   Reading domain options from xml.
        /// </summary>
        [TestMethod]
        public void ReadingDomainOptionsFromXml()
        {
            // Creating a backup
            var xml = string.Format("<{0}>",
                BackupDto.XmlTag);

            // Creating the domain option list
            xml += string.Format("<{0} {1}=\"{2}\" /><{3} {4}=\"{5}\"></{6}></{7}>",
                DomainOptionsDto.XmlTag,
                DomainOptionsDto.HasRecycleBinAttribute,
                "True",
                DomainOptionsDto.XmlTag,
                DomainOptionsDto.HasRecycleBinAttribute,
                "False",
                DomainOptionsDto.XmlTag,
                BackupDto.XmlTag);

            var stream = new XmlTextReader(new MemoryStream(Encoding.UTF8.GetBytes(xml)));

            var dto = new BackupDto();

            dto.ReadXml(stream);

            Assert.IsNotNull(dto.Options);
            Assert.IsNotNull(dto.Options.HasRecycleBin);
            Assert.IsFalse(dto.Options.HasRecycleBin.Value);
        }


        /// <summary>
        ///   Writing and reading domain options.
        /// </summary>
        [TestMethod]
        public void WritingAndReadingDomainOptions()
        {
            var backupDto = new BackupDto
                                {
                                    Options = new DomainOptionsDto
                                                  {
                                                      HasRecycleBin = false
                                                  }
                                };


            var memoryStream = new MemoryStream();
            var writer = new XmlTextWriter(memoryStream, Encoding.UTF8);

            backupDto.WriteXml(writer);

            writer.Flush();

            memoryStream.Position = 0;
            var streamReader = new StreamReader(memoryStream);
            var xml = streamReader.ReadToEnd();

            Assert.IsFalse(string.IsNullOrEmpty(xml));

            memoryStream.Position = 0;
            var reader = new XmlTextReader(memoryStream);

            var dto = new BackupDto();

            dto.ReadXml(reader);

            Assert.IsNotNull(dto.Options);
            Assert.IsNotNull(dto.Options.HasRecycleBin);
            Assert.IsFalse(dto.Options.HasRecycleBin.Value);
        }
    }
}
